/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ssp.utility;

import ec.util.MersenneTwister;
import java.io.Serializable;
import java.util.logging.Level;
import ssp.ResourceManager;
import ssp.SimulationManager;

/**
 * メルセンヌ・ツイスタによる乱数生成のためのクラス
 * @author yamazaki
 */
public class MersenneTwisterRNG extends MersenneTwister
                                    implements ResourceManager, Serializable {
    
    private static final long serialVersionUID = 5531768610976126058L;
    
    /**
     * 乱数の種<br>
     * プロパティファイルから取得する
     */
    private static long seed = PropertyManager.getValueAsLong("SeedForRNG");
    
    /**
     * シミュレーション中で唯一のクラスインスタンス
     */
    private static MersenneTwisterRNG INSTANCE = new MersenneTwisterRNG(seed);
    
    /**
     * コンストラクタ<br>
     * シングルトンのためprivateアクセス
     * @param seed 乱数の種
     */
    private MersenneTwisterRNG(long seed) {
        super(seed);
        SimulationManager.register(this);
        LoggingManager.logging(Level.INFO, "Seed number is " + getSeed(), new Throwable());
    }

    /**
     * @return the seed
     */
    public static long getSeed() {
        return seed;
    }

    /**
     * @return the INSTANCE
     */
    public static MersenneTwisterRNG getINSTANCE() {
        return INSTANCE;
    }
    
    @Override
    public void init() {
        this.setSeed(seed++);
        LoggingManager.logging(Level.INFO, "Seed number is " + getSeed(), new Throwable());
    }

    /**
     * パラメータmuの指数分布に従う乱数を生成
     * @param mu 指数分布のパラメータ 1/avg.
     * @return 乱数
     */
    public double nextExponetial(double mu) {
        if(mu == 0.0) {
            throw new IllegalArgumentException();
        }
        
        return -Math.log((1.0 - this.nextDouble())) / mu;
    }
    
}
